using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using NetPong;

namespace XNALibrary
{
    public class RigidBody
    {
        #region Fields and properties

        // Shape
        protected Model model;
        protected Texture2D texture;
        protected float scale = 1.0f, scaleX = 1.0f, scaleY = 1.0f, scaleZ = 1.0f;

        // Position and linear velocity of CM
        protected Vector3 position = Vector3.Zero;
        protected Vector3 linearVelocity = Vector3.Zero;
        protected float friction;

        // Orientation and angular velocity
        protected Quaternion orientation = Quaternion.Identity;
        protected Matrix rotation = Matrix.Identity;
        protected Vector3 angularVelocity = Vector3.Zero;

        public RigidBody(Model m)
        {
            model = m;
            friction = .99f;
            scale = 1.0f;
            scaleX = 1.0f;
            scaleY = 1.0f;
            scaleZ = 1.0f;
            
        }

        public Model Model
        {
            set { model = value; }
        }

        public virtual Vector3 Position
        {
            get { return position; }
            set { position = value; }
        }

        public virtual Vector3 LinearVelocity
        {
            get { return linearVelocity; }
            set { linearVelocity = value; }
        }

        public virtual Vector3 AngularVelocity
        {
            get { return angularVelocity; }
            set { angularVelocity = value; }
        }

        public virtual Matrix Rotation
        {
            get { return rotation; }
            set { rotation = value; }
        }

        public float Scale
        {
            get { return scale; }
            set { scale = value; }
        }

        #endregion Fields and properties

        public virtual void Initialize()
        {

        }

        public Matrix GetWorld(ModelMesh mesh)
        {
            Matrix[] transforms = new Matrix[model.Bones.Count];
            model.CopyAbsoluteBoneTransformsTo(transforms);
            return transforms[mesh.ParentBone.Index]
                            * Matrix.CreateScale(scale)
                            * rotation
                            * Matrix.CreateTranslation(Position);
        }
        
        public virtual void Update()
        {
            position += linearVelocity;

            // Apply friction, i.e decay velocity
            linearVelocity *= friction;
        }

        public virtual void Reset()
        {
            position = Vector3.Zero;
            linearVelocity = Vector3.Zero;

            orientation = Quaternion.Identity;
            rotation = Matrix.Identity;
            angularVelocity = Vector3.Zero;
        }

        public virtual void Draw(Matrix view, Matrix projection, RenderControl rc)
        {
            if (model == null) return;

            // Draw the model. A model can have multiple meshes, so loop.
            foreach (ModelMesh mesh in model.Meshes)
            {
                // This is where the mesh orientation is set, as well as our camera and projection.
                foreach (BasicEffect effect in mesh.Effects)
                {
                    //effect.EnableDefaultLighting();
                    effect.World = GetWorld(mesh);
                    effect.View = view;
                    effect.Projection = projection;
                    if (texture != null)
                    {
                        effect.Texture = texture;
                        effect.TextureEnabled = true;
                    }
                }
                // Draw the mesh, using the effects set above.
                mesh.Draw();
            }
        }

    }
}
